package com.gitee.l0km.xthrift.base.doc;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import com.gitee.l0km.com4j.basex.doc.ClassCommentProvider;
import com.gitee.l0km.com4j.basex.doc.ClassCommentProviderFactory;
import com.gitee.l0km.xthrift.base.ThriftDecorator;
import com.google.common.collect.ImmutableList;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * 基于代理类型优先(Delegate Firstly)策略实现{@link ClassCommentProvider}接口<br>
 * 如果类型为装饰类(实现了ThriftDecorator接口)，则优先使用代理类型的注释
 * 
 * @author guyadong
 * @since 2.4.0
 *
 */
public class DelegateFirstlyProvider implements ClassCommentProvider {

	private final ClassCommentProvider classCommitProvider;
	/**
	 * 如果类型({@link #clazz})为装饰类(实现了ThriftDecorator接口)，
	 * 此字段为其代理类型对应的{@link ClassCommentProvider}实例，否则为{@code null}
	 */
	private final ClassCommentProvider decoratorCommitProvider;

	DelegateFirstlyProvider(ClassCommentProviderFactory factory, Class<?> clazz) {
		this.classCommitProvider = checkNotNull(factory, "factory is null").apply(checkNotNull(clazz));
		Class<?> delegateClass = delegateClassOf(clazz);
		this.decoratorCommitProvider = null == delegateClass ? null : factory.apply(delegateClass);
	}

	@Override
	public List<String> commentOfClass() {
		List<String> cmt = ImmutableList.of();
		/** 类型为装饰类(实现了ThriftDecorator接口)，则优先使用代理类型的注释 */
		if (null != decoratorCommitProvider) {
			cmt = decoratorCommitProvider.commentOfClass();
		}
		return !cmt.isEmpty() ? cmt : classCommitProvider.commentOfClass();
	}

	@Override
	public List<String> commentOfMethod(Method method, boolean withTags) {
		List<String> cmt = ImmutableList.of();
		/** 类型为装饰类(实现了ThriftDecorator接口)，则优先使用代理类型的注释 */
		if (null != decoratorCommitProvider) {
			cmt = decoratorCommitProvider.commentOfMethod(method, withTags);
		}
		return !cmt.isEmpty() ? cmt : classCommitProvider.commentOfMethod(method, withTags);
	}

	@Override
	public List<String> commentOfField(String name) {
		List<String> cmt = ImmutableList.of();
		/** 类型为装饰类(实现了ThriftDecorator接口)，则优先使用代理类型的注释 */
		if (null != decoratorCommitProvider) {
			cmt = decoratorCommitProvider.commentOfField(name);
		}
		return !cmt.isEmpty() ? cmt : classCommitProvider.commentOfField(name);
	}

	/**
	 * 如果{@code clazz}实现了{@link ThriftDecorator}接口，则返回其代理类型，否则返回{@code null}
	 * 
	 * @param clazz
	 */
	private static Class<?> delegateClassOf(Class<?> clazz) {
		if (null != clazz && ThriftDecorator.class.isAssignableFrom(clazz)) {
			Type[] types = clazz.getGenericInterfaces();
			for (Type type : types) {
				if (type instanceof ParameterizedType) {
					ParameterizedType parameterizedType = ((ParameterizedType) type);
					if (parameterizedType.getRawType() instanceof Class<?>
							&& ThriftDecorator.class.isAssignableFrom((Class<?>) parameterizedType.getRawType())) {
						Type a0 = parameterizedType.getActualTypeArguments()[0];
						return a0 instanceof Class ? (Class<?>) a0 : null;
					}
				}
			}
		}
		return null;
	}
}
